package com.followerback.resources;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;

import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.User;
import twitter4j.auth.AccessToken;
import twitter4j.auth.RequestToken;

import com.followerback.model.TwitterProfile;
import com.followerback.model.TwitterProfileChannel;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyService;

@Path("/oauth")
public class OAuthResource extends Resource {
	
	private static final Logger logger = Logger.getLogger(OAuthResource.class.getName());
	
	@Path("/authenticate")
	@GET
	@Produces(MediaType.TEXT_PLAIN)
	public Response authenticate(@Context HttpServletRequest request) throws TwitterException, URISyntaxException {
		Twitter twitter = twitterFactory.getInstance();
		
		StringBuffer callbackURL = request.getRequestURL();
        int index = callbackURL.lastIndexOf("/");
        callbackURL.replace(index, callbackURL.length(), "").append("/callback");

        RequestToken requestToken = twitter.getOAuthRequestToken(callbackURL.toString());
	    
		ResponseBuilder responseBuilder = Response.temporaryRedirect(new URI(requestToken.getAuthenticationURL()));
		request.getSession().setAttribute("requestToken", requestToken);
	    
	    return responseBuilder.build();
	}
	
	@Path("/callback")
	@GET
	@Produces(MediaType.TEXT_PLAIN)
	public Response storeAccessToken(@QueryParam("oauth_token") @DefaultValue("") String oauthToken,
			@QueryParam("oauth_verifier") @DefaultValue("") String oauthVerifier, 
			@Context HttpServletRequest request) throws TwitterException, URISyntaxException {
		
		
		/* Initial stuff */
		logger.info("Entering storeAccessToken");
		long methodStartTime = System.currentTimeMillis();
		if(oauthToken.isEmpty() || oauthVerifier.isEmpty()) {
			String errorReason = "Missing required params";
			logger.severe(errorReason);
			return Response.serverError().build();
		}
		Objectify objectify = ObjectifyService.begin();
		Twitter twitter = twitterFactory.getInstance();
		
		
		/* Get request Token */
		RequestToken requestToken = (RequestToken) request.getSession().getAttribute("requestToken");
		AccessToken accessToken = twitter.getOAuthAccessToken(requestToken, oauthVerifier);
		
		
		/* Save user to db */
		// get user
		long userID = accessToken.getUserId();
		User user = twitter.showUser(userID);
		
		// check for existing profile first and handle accordingly
		TwitterProfile twitterProfile = objectify.query(TwitterProfile.class)
				.filter("userID", userID).get();
		if(twitterProfile == null) {
			twitterProfile = new TwitterProfile(userID, accessToken.getScreenName(), 
					user.getBiggerProfileImageURL(), accessToken.getToken(), accessToken.getTokenSecret());
		} else {
			twitterProfile.setPictureURL(user.getBiggerProfileImageURL());
			twitterProfile.setToken(accessToken.getToken());
			twitterProfile.setTokenSecret(accessToken.getTokenSecret());
		}
		objectify.put(twitterProfile);
		postToSaveFollowers(twitterProfile.getId());
		postToSaveFriends(twitterProfile.getId());
	    
		// save id in session
		HttpSession httpSession = request.getSession();
		httpSession.setAttribute("serverSideUserID", twitterProfile.getId());

		
		/* End Stuff */
		logger.info("Exiting storeAccessToken in " 
				+(System.currentTimeMillis() - methodStartTime)/1000d+ " secs");
	    return Response.temporaryRedirect(new URI(Resource.baseURL)).build();
	}
	
	@Path("/check")
	@GET
	@Produces(MediaType.APPLICATION_JSON)
	public Response isAuthenticated(@Context HttpServletRequest request) {
		
		
		/* Initial stuff */
		logger.info("Entering isAuthenticated");
		long methodStartTime = System.currentTimeMillis();
		HttpSession httpSession = request.getSession(true);
		Long userID = (Long)httpSession.getAttribute("serverSideUserID");
		if(userID == null)
			return Response.status(401).build();
		Objectify objectify = ObjectifyService.begin();
		
		
		/* Get Profile */
		TwitterProfile twitterProfile = objectify.find(TwitterProfile.class, userID);
		if(twitterProfile == null)
			return Response.status(401).build();
		TwitterProfileChannel twitterProfileChannel = objectify.query(TwitterProfileChannel.class)
				.filter("twitterProfileID", userID).get();
		
		// return user profile params
		Map<String, Object> userMap = new HashMap<String, Object>();
		userMap.put("id", twitterProfile.getId());
		userMap.put("name", twitterProfile.getScreenName());
		userMap.put("picture", twitterProfile.getPictureURL());
		if(twitterProfileChannel != null)
			userMap.put("token", twitterProfileChannel.getChannelToken());
		
		
		/* End Stuff */
		logger.info("Exiting isAuthenticated in " 
				+(System.currentTimeMillis() - methodStartTime)/1000d+ " secs");
		return Response.ok(gson.toJson(userMap)).build();
	}
}
